Щелкните правой кнопкой мыши на src, чтобы создать новую папку:
Создайте соответствующие файлы .c и .h:
Как показано ниже:
На этом этапе, аналогично операциям с GPIO, если есть пользовательские заголовочные файлы, необходимо добавить каталог файлов в путь. Шаги такие же, как и выше, и конечный результат показан ниже:
x// инициализация устройства EEPROMint eeprom_init(const char *i2c_dev) { int fd = open(i2c_dev, O_RDWR); if (fd < 0) { perror("Failed to open I2C bus"); return -1; }
if (ioctl(fd, I2C_SLAVE, EEPROM_ADDR) < 0) { perror("Failed to set I2C address"); close(fd); return -1; }
return fd;}
// Запись данных в EEPROMbool eeprom_write(int fd, unsigned short addr, const unsigned char *data, unsigned int len) { if (fd < 0 || data == NULL || len == 0) { return false; }
// Создание буфера данных для записи unsigned char *buf = malloc(len + 2); if (buf == NULL) { perror("Memory allocation failed"); return false; }
// Установка адреса (16-битного) buf[0] = (addr >> 8) & 0xFF; // Старший байт buf[1] = addr & 0xFF; // Младший байт
// копирование данных memcpy(buf + 2, data, len);
// запись данных if (write(fd, buf, len + 2) != (len + 2)) { perror("EEPROM write failed"); free(buf); return false; }
free(buf); usleep(10000); // Ожидание завершения записи return true;}
// Чтение данных из EEPROMbool eeprom_read(int fd, unsigned short addr, unsigned char *data, unsigned int len) { if (fd < 0 || data == NULL || len == 0) { return false; }
// Установка адреса для чтения (16-битного) unsigned char addr_buf[2]; addr_buf[0] = (addr >> 8) & 0xFF; // Старший байт addr_buf[1] = addr & 0xFF; // Младший байт
if (write(fd, addr_buf, 2) != 2) { perror("EEPROM set read address failed"); return false; }
// чтение данных if (read(fd, data, len) != len) { perror("EEPROM read failed"); return false; }
return true;}
// Закрытие устройства EEPROMvoid eeprom_close(int fd) { if (fd >= 0) { close(fd); }}Щелкните правой кнопкой мыши на src, чтобы создать новую папку:
Создайте соответствующие файлы .c и .h, как показано ниже:
xxxxxxxxxx// инициализация датчика shtc3int shtc3_init(const char *i2c_dev) { int fd = open(i2c_dev, O_RDWR); if (fd < 0) { perror("Failed to open I2C bus"); return -1; }
if (ioctl(fd, I2C_SLAVE, SHTC3_ADDR) < 0) { perror("Failed to open SHTC3 device"); close(fd); return -1; }
return fd;}
// Чтение данных с датчика SHTC3bool shtc3_read_data(int fd, shtc3_data_t *data) { unsigned char cmd[2]; unsigned char sensor_data[6];
if (fd < 0 || data == NULL) { return false; }
// Пробуждение датчика cmd[0] = (CMD_WAKEUP >> 8) & 0xFF; cmd[1] = CMD_WAKEUP & 0xFF; if (write(fd, cmd, 2) != 2) { perror("SHTC3 wakeup failed"); return false; } usleep(1000);
// Отправка команды измерения cmd[0] = (CMD_MEASURE >> 8) & 0xFF; cmd[1] = CMD_MEASURE & 0xFF; if (write(fd, cmd, 2) != 2) { perror("SHTC3 measure command failed"); return false; } usleep(20000);
// Чтение 6 байт данных if (read(fd, sensor_data, 6) != 6) { perror("Failed to read SHTC3 data"); return false; }
// Преобразование сырых данных uint16_t raw_temp = (sensor_data[0] << 8) | sensor_data[1]; uint16_t raw_hum = (sensor_data[3] << 8) | sensor_data[4];
// Вычисление температуры и влажности data->temperature = -45 + 175 * ((float)raw_temp / 65535.0); data->humidity = 100 * ((float)raw_hum / 65535.0);
return true;}
// Закрытие устройства датчика SHTC3void shtc3_close(int fd) { if (fd >= 0) { unsigned char cmd[2]; // Отправка команды сна cmd[0] = (CMD_SLEEP >> 8) & 0xFF; cmd[1] = CCMD_SLEEP & 0xFF; write(fd, cmd, 2); close(fd); }}
Щелкните правой кнопкой мыши на src, чтобы создать новую папку:
Создайте соответствующие файлы .c и .h, как показано ниже:
xxxxxxxxxx// использовать RTC PCF8563 или RTC PCF85063
unsigned char dec2bcd(int dec) { return ((dec / 10) << 4) | (dec % 10);}
uint8_t bcd2dec(uint8_t bcd) { return ((bcd >> 4) * 10) + (bcd & 0x0F);}
int open_rtc_dev(const char *i2c_dev){ uint8_t buf[2]; // Адрес регистра + 1 байт данных uint8_t slave_addr = PCF85063_SLAVE_ADDR; // Адрес ведомого устройства по умолчанию для PCF85063 int fd = open(i2c_dev, O_RDWR); if (fd < 0) { perror("Failed to open I2C bus"); return -1; }
slave_addr = PCF8563_DEVICE_ADDR; // Использовать адрес PCF8563, если определено
if (ioctl(fd, I2C_SLAVE, slave_addr) < 0) { perror("Failed to set I2C address"); close(fd); return -1; }
unsigned char reg = 0x04; if (fd < 0) { return false; }
// сброс PCF8563 buf[0] = PCF8563_REG_CONTROL_STATUS1; buf[1] = 0x00; if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { perror("set_rtc write failed"); return false; }
// отключить будильник PCF8563 buf[0] = PCF8563_REG_CONTROL_STATUS2; buf[1] = 0x00; if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { perror("set_rtc write failed"); return false; }
// Отключить тактовый выход buf[0] = PCF8563_REG_CLKOUT_CONTROL; buf[1] = 0x00; if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { perror("set_rtc write failed"); return false; }
// отключить таймер buf[0] = PCF8563_REG_TIMER_CONTROL; buf[1] = 0x00; if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { perror("set_rtc write failed"); return false; } // сброс PCF85063 buf[0] = PCF85063_REG_CONTROL1; buf[1] = 0x00; if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { perror("set_rtc write failed"); return false; }
// Отключить функцию будильника и прерывание таймера buf[0] = PCF85063_REG_CONTROL2; buf[1] = 0x00; if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { perror("set_rtc write failed"); return false; }
// Отключить тактовый выход buf[0] = PCF85063_REG_TIMER_MODE; buf[1] = 0x00; if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { perror("set_rtc write failed"); return false; }
return fd;}
bool read_rtc(int fd, stDateTime *dt){ unsigned char reg = PCF85063_REG_SECONDS; // чтение из регистра секунд unsigned char data[7];
if (fd < 0 || dt == NULL) { return false; }
reg = PCF8563_REG_VL_SEC; // чтение из регистра секунд для PCF8563
// Установить начальный адрес для чтения (запись 0x04 if (write(fd, ®, 1) != 1) { perror("set read register failed"); return false; }
// Прочитать 7 байт if (read(fd, data, 7) != 7) { perror("read rtc failed"); return false; }
dt->second = bcd2dec(data[0] & 0x7F); dt->minute = bcd2dec(data[1] & 0x7F); dt->hour = bcd2dec(data[2] & 0x3F); dt->day = bcd2dec(data[3] & 0x3F); dt->weekday = bcd2dec(data[4] & 0x07); dt->month = bcd2dec(data[5] & 0x1F); dt->year = bcd2dec(data[6]);
return true;}
bool set_rtc(int fd, const stDateTime *dt){ unsigned char reg = PCF85063_REG_SECONDS; if (fd < 0) { return false; }
reg = PCF8563_REG_VL_SEC; // чтение из регистра секунд для PCF8563
// Создать буфер данных для записи uint8_t buf[8]; // Заголовок регистра (1 байт) + поле данных 7 байт buf[0] = reg; // Начальный адрес регистра для записи buf[1] = dec2bcd(dt->second); buf[2] = dec2bcd(dt->minute); buf[3] = dec2bcd(dt->hour); buf[4] = dec2bcd(dt->day); buf[5] = dec2bcd(dt->weekday); buf[6] = dec2bcd(dt->month); buf[7] = dec2bcd(dt->year % 100);
// Записать все данные за один раз if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { perror("set_rtc write failed"); return false; }
return true;}
void close_rtc_dev(int fd){ if (fd >= 0) { close(fd); // Закрыть входящий файловый дескриптор }}
Откройте файл /home/mind/petalinux_projects/petalinux-mind/project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi и добавьте следующее содержимое:
xxxxxxxxxx&i2c0 {
clock-frequency = <100000>; rtc@51{ compatible="nxp,pcf8563"; reg=<0x51>; };};После внесения изменений сохраните и выйдите, затем повторно выполните следующие шаги:
xxxxxxxxxxpetalinux-buildpetalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf --u-boot --fpga --forceСкопируйте файлы BOOT.BIN, boot.scr и image.ub из каталога проекта images -> linux в раздел FAT SD-карты. Файловая система остаётся без изменений. Перезагрузите плату разработки.
После перезагрузки системы проверьте каталог /dev/ на наличие файлов устройств, связанных с RTC, как показано ниже:
Видно, что в каталоге /dev есть два файла устройств: rtc и rtc0, где rtc — это программная ссылка на rtc0. rtc0 соответствует нашему устройству pcf8563. Если в системе не зарегистрировано ни одного устройства RTC (с помощью фреймворка драйверов устройств RTC Linux), в каталоге /dev не будет файлов устройств RTC. Если в ядре зарегистрировано несколько устройств RTC, они будут иметь имена rtc0, rtc1, rtc2 и т. д. В каталоге /sys/class есть каталог rtc, в котором находятся следующие файлы:
Здесь rtc0 соответствует устройству pcf8563.
(1) Время просмотра:
Команда date показывает системные часы, а не часы RTC. Системные часы поддерживаются ядром после запуска системы, а не аппаратными часами RTC. Для просмотра показаний часов RTC используйте команду hwclock.
xxxxxxxxxxdatehwclock(2) Установите время RTC:
После настройки снова используйте команду date, чтобы увидеть, что текущее время изменилось.
xxxxxxxxxxdate -s "2023-09-22 15:19:36"date(3) Написать в РТК:
xxxxxxxxxxhwclock -wВ этом случае время не будет сбиваться даже после перезагрузки системы. Если к плате разработки подключена батарейка типа «таблетка», время не будет сбиваться даже при выключении платы.
xxxxxxxxxxroot@petalinux-mind:~# dateThu Aug 21 13:46:37 UTC 2025